home *** CD-ROM | disk | FTP | other *** search
- /*********************************************************************
-
- Scroll.c
-
- Programmed by Keith Lambert 1986,87
- Compuserve 75076,34
- GEnie K.Lambert
-
- OR
-
- 3433 Marathon Drive
- San Diego, Calif. 92123
-
- Please leave me mail if you have any problems or questions with this
- code.
-
- This file is for the LightspeedC development system. If you are not
- using this system, you will have to make the neccessary adjustments.
-
- This program will display a Modal Dialog box that contains a
- scrollable list of items similiar to the SFGetFile. However this
- program does not use any list manager routines.
-
- This program is meant to be an example only, and it might serve as a
- template for your own application.
- There are no general routines to build a dynamic text list for display
- in the dialog. This is left up to the specific application. This example
- only uses a list of 20 strings that are in a global array for its text.
-
- This code contains some examples on using filter procedures and
- user item procedures for modal dialog boxes.
-
- *********************************************************************/
-
-
-
- #include "QuickDraw.h"
- #include "MacTypes.h"
- #include "FontMgr.h"
- #include "WindowMgr.h"
- #include "MenuMgr.h"
- #include "TextEdit.h"
- #include "DialogMgr.h"
- #include "EventMgr.h"
- #include "DeskMgr.h"
- #include "FileMgr.h"
- #include "ToolboxUtil.h"
- #include "ControlMgr.h"
- #include "strings.h"
- #include "ctype.h"
- #include "types.h"
- #include "pascal.h"
- #include "Scroll.h"
-
- #define NUMSTRS 20 /* number of strings in dialog */
- #define SCROLLDELAY 10000 /* to slow down scrolling a little*/
-
-
- /* GLOBAL VARIABLES */
-
- EventRecord myEvent;
- DialogPtr myWindow; /*ptr to the dialog window*/
- WindowPtr EvWindow; /* Event window*/
- MenuHandle myMenus[4];
-
- short startValue,endValue; /* scroll bar values */
- int MIN = 0 , MAX ; /* min and max values for scroll bar*/
- int LinesShow; /* number of lines in scroll box*/
- int height; /* line height in text edit record*/
-
- TEHandle theText; /* Handle to the text edit record */
-
-
- /* the text items in the scrolling dialog */
- /* normally you would have to build this list dynamically in your application */
- /* but since this is just an example program, let keep it simple. */
- char *Strs[] = {
- "Airborne\r",
- "Archon\r",
- "Cyborg\r",
- "Gato\r",
- "Grid Wars\r",
- "Lode Runner\r",
- "MacGolf\r",
- "Maze Wars+\r",
- "Mystery Box\r",
- "Orbiter\r",
- "Orbquest\r",
- "Pinball\r",
- "Rogue\r",
- "Sargon\r",
- "Shanghai\r",
- "SkyFox\r",
- "Think Ahead+\r",
- "Winter Games\r",
- "Wizardry\r",
- "Zork\r"
- } ;
-
-
-
-
- restartProc()
- {
- ExitToShell();
- }
-
- Init()
- {
- MaxApplZone();
- MoreMasters();
- MoreMasters();
- MoreMasters();
- InitGraf(&thePort);
- InitFonts();
- FlushEvents( everyEvent, 0 );
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(&restartProc);
- InitCursor();
- SetUpMenus();
-
-
- } /* end Init(); */
-
-
- main()
- {
- Init();
-
- while (MainEvent()) ;
- }
-
-
- int MainEvent()
- {
-
- WindowPtr whichWindow;
-
- SystemTask();
-
- if (GetNextEvent(everyEvent, &myEvent))
- {
-
-
- switch (myEvent.what)
- {
- case mouseDown:
- switch (FindWindow( myEvent.where, &whichWindow ))
- {
- case inDesk:
- SysBeep(10);
- break;
- case inGoAway:
- break;
- case inMenuBar:
- DoCommand( MenuSelect(myEvent.where) );
- case inSysWindow:
- SystemClick( &myEvent, whichWindow );
- break;
- case inDrag:
- break;
- case inGrow:
- break;
- case inContent:
- checkClick();
- break;
- default: ;
- } /* end switch FindWindow */
- break;
-
- case keyDown:
- case autoKey:
- if ((myEvent.modifiers & cmdKey)) /* menu equivalent ?*/
- DoCommand(MenuKey(myEvent.message));
- break;
- case activateEvt:
- break;
- case updateEvt: /* Someone said window needs refresh*/
- EvWindow = (WindowPtr)myEvent.message; /* Which window?*/
- UpdateWind(EvWindow); /* Do the update*/
- break;
-
-
- default:
- break;
- } /* end of case myEvent.what */
- } /* if */
-
-
-
- return(1);
- }
-
- SetUpMenus()
- {
- int i;
-
- myMenus[appleM] = GetMenu(appleID);
- AddResMenu( myMenus[appleM], 'DRVR' );
- myMenus[fileM] = GetMenu(fileID);
- myMenus[editM] = GetMenu(editID);
- myMenus[dlogM] = GetMenu(DialogID);
-
- for ( (i=appleM); (i<=dlogM); i++ ) InsertMenu(myMenus[i], 0) ;
- DrawMenuBar();
-
-
- }
-
-
- int DoCommand( mResult )
- long mResult;
- {
- short theItem;
- Str255 name;
- GrafPtr savePort;
- long size,memAvail;
- Handle myResHandle,myHandle;
-
-
- theItem = LoWord( mResult );
- switch (HiWord(mResult))
- {
- case appleID:
- if (theItem == 1)
- BragAbout();
- else
- { /* check memory before opening DA, */
- GetItem(myMenus[appleM], theItem, &name);
- SetResLoad(FALSE);
- myResHandle = GetNamedResource('DRVR',&name);
- size = SizeResource(myResHandle) + 3072;
- SetResLoad(TRUE);
- if((memAvail = CompactMem(size)) > size )
- {
- GetPort(&savePort);
- OpenDeskAcc( &name );
- SetPort(savePort);
- }
- else
- SysBeep(5); /* not enough memouy ! */
-
- }
-
- break;
- case fileID:
- DoFile(theItem);
- break;
- case editID:
- if(SystemEdit(theItem-1));
- break;
- case DialogID:
- DoDialogMenu(theItem);
- break;
- }
- HiliteMenu(0);
- return(1);
- }
-
- /*============================================================================
- Procedure DoFile():
- Process all File menu selections here.
- ============================================================================*/
- DoFile(item)
- int item;
- {
- switch(item)
- {
- case 1: /* QUIT*/
- ExitToShell();
- break;
- }
-
- }
-
- /*============================================================================
- Procedure DoDialogMenu():
- Process all dialog menu selections here.
- ============================================================================*/
-
- DoDialogMenu(item)
- short item;
- {
-
- switch(item)
- {
- case 1:
- DoDialog1();
- break;
-
- }
-
- } /* end DoOptMenu() */
-
-
-
- /*============================================================================
- * Procedure BragAbout:
- * Display a dialog box that tells a little about the program.
- *============================================================================*/
- BragAbout()
- {
- short itemHit;
- GrafPtr savePort;
- Handle iconHand;
-
-
- GetPort(&savePort); /* save the current port*/
- myWindow = GetNewDialog(100,0,-1);
- SetPort(myWindow);
- itemHit = 0;
-
- while(itemHit < 1) /* while not in Ok*/
- {
- ModalDialog(0,&itemHit); /* wait for mouse click*/
- }
-
- DisposDialog(myWindow);
- SetPort(savePort);
-
-
- } /* END BragAbout*/
-
- /*==============================================================================
- * Dobold()
- * this is the user item procedure to make the thick outline around the default
- * button ( assumed to be item 1)
- *=============================================================================*/
-
- pascal void Dobold(dlogPtr,item)
- DialogPtr dlogPtr;
- unsigned short item;
- {
- unsigned short itype;
- Handle ihandle;
- Rect irect;
-
- GetDItem(dlogPtr,1,&itype,&ihandle,&irect); /* get the buttons rect */
- PenSize(3,3); /* make thick lines */
- InsetRect(&irect,-4,-4); /* grow rect a little */
- FrameRoundRect(&irect,16,16); /* frame the button now */
- PenNormal();
-
- }
-
-
- /*=============================================================================
- * DrawScrollText()
- * this the the user item procedure for the scrolling items display. It will
- * draw the rectangle around the text and set up text edit record for the
- * items in the dialog.
- * for some reason I couldn't get the rectangle of the useritem so I could
- * draw a rectangle around it, so instead I got the rect of the scrollbar
- * and adjusted that rect to the appropriate size.
- *============================================================================*/
-
- pascal void DrawScrollText(dlogPtr,item)
- DialogPtr dlogPtr;
- unsigned short item;
- {
- register int x;
- unsigned short itype;
- Handle ihandle;
- Rect irect,theRect,viewRect,destRect;
-
-
-
- GetDItem(dlogPtr,4,&itype,&ihandle,&irect); /* get the scroll bars rect*/
-
- BlockMove(&irect,&theRect,sizeof(Rect)); /* copy the rect */
- theRect.left -= 120; /* adjust left and right sides*/
- theRect.right -= 15;
-
- FrameRect(&theRect);
-
- BlockMove(&theRect,&viewRect,sizeof(Rect));
- InsetRect(&viewRect,1,1); /* shrink viewRect a little*/
-
- BlockMove(&viewRect,&destRect,sizeof(Rect));
-
-
- theText = TENew(&destRect,&viewRect); /* setup textedit record*/
-
- height = (*theText)->lineHeight; /* line height in pixels */
-
- /* calculate how many lines will show in the rectangle */
- LinesShow = (viewRect.bottom-viewRect.top)/height;
-
- /* set the control max to the number of strings - how many will show */
- MAX = (NUMSTRS - LinesShow);
-
-
- SetCtlMin(ihandle,MIN); /* set the control values */
- SetCtlMax(ihandle,MAX);
- SetCtlValue(ihandle,MIN);
-
-
- for(x=0;x<NUMSTRS;x++) /* insert the strings into record*/
- {
- TEInsert(Strs[x],strlen(Strs[x]),theText);
-
- }
-
-
- }
-
-
- /*=============================================================================
- * scrollAction()
- * this is the action procedure that is used whenever the mouse is held down in
- * the scroll bar arrow or page regions. Basically all it does is set the
- * control value and then call scrolltext. This procedure executes so fast that
- * holding down the mouse in the up or down arrows will scroll by more that one
- * line every time so a small dealy has be inserted at the end to adjust it so
- * it will scroll only one line.
- *============================================================================*/
-
- pascal void scrollAction(theControl,partcode)
- ControlHandle theControl;
- short partcode;
- {
- register int x;
-
- startValue = GetCtlValue(theControl);
-
- switch(partcode)
- {
- case inUpButton:
- if(startValue > MIN ) /* to avoid rattling scroll box */
- {
- SetCtlValue(theControl, startValue - 1 );
- ScrollText(theControl);
- }
- break;
-
- case inDownButton:
- if(startValue < MAX )
- {
- SetCtlValue(theControl, startValue + 1 );
- ScrollText(theControl);
- }
- break;
-
- case inPageUp:
- if(startValue > MIN )
- {
- SetCtlValue(theControl, startValue - (LinesShow-1));
- ScrollText(theControl);
- }
- break;
-
- case inPageDown:
- if(startValue < MAX )
- {
- SetCtlValue(theControl, startValue + (LinesShow-1));
- ScrollText(theControl);
- }
- break;
- }
-
-
- endValue = GetCtlValue(theControl); /* not really used here */
-
-
- for(x=0;x<SCROLLDELAY;x++); /* slow down scrolling, too fast otherwise */
- }
-
-
-
- /*==============================================================================
- * ScrollText()
- * this procedure will scroll the text in the text edit record after the scroll
- * bar has been adjusted/
- *============================================================================*/
-
- ScrollText(theControl)
- ControlHandle theControl;
- {
-
- RgnHandle updateRgn;
- int scrollValue,scrollDiff,oldScroll,newScroll,ViewTop,DestTop;
-
-
-
-
- ViewTop = (*theText)->viewRect.top;
- DestTop = (*theText)->destRect.top;
-
- oldScroll = (ViewTop - DestTop);
- scrollValue = GetCtlValue(theControl);
-
- newScroll = (scrollValue * height);
- scrollDiff = (oldScroll - newScroll);
-
- if (scrollDiff != 0)
- TEScroll(0,scrollDiff,theText);
-
-
- }
- /*============================================================================
- * scrollFilter()
- * this is the filter proc for the modal dialog. It handles events the way I
- * want them. keyDown events will be checked for the RETURN of ENTER keys and be
- * treated like a press in the OK button. Pressing the TILDE key will be treated
- * like the CANCEL button. All other key presses are ignored.
- * mouseDown events are checked to see if they are in the SCROLL BAR or the
- * rectangle containg the scrolling text. Other mouse downs are handled by
- * ModalDialog.
- *===========================================================================*/
-
- pascal char scrollFilter(dp,event,item)
- DialogPtr dp;
- EventRecord *event;
- unsigned short *item;
- {
- char c,result;
- char choosenText[25]; /* storage space for text selected */
- Rect irect;
- Point eventPoint;
- ControlHandle whichControl;
- Handle ihandle,TES;
- short partcode,bogus,finalTicks;
- long startSel,endSel,length;
- int DestTop,scrollValue,lineHit,x;
- unsigned short itype;
-
-
-
- result = FALSE;
-
- if(event->what == keyDown) /* we have a key press */
- {
-
- c = event->message & 0x00FF; /* what character is it? */
- if(c == 0x0003 || c == 0x000D) /* return or enter keys */
- {
- GetDItem(dp,1,&itype,&ihandle,&irect);
- HiliteControl(ihandle,1); /* pretend user clicked in button*/
- Delay(4,finalTicks); /* keep it on screen a moment */
- result = TRUE;
- *item = 1; /*select the default button */
- }
- else
- {
- if(c == 0x0060 || c == 0x007E ) /*use tilde key for Cancel button*/
- { GetDItem(dp,2,&itype,&ihandle,&irect);
- HiliteControl(ihandle,1);
- Delay(4,finalTicks);
- result = TRUE;
- *item = 2; /* treat as the cancel button */
- }
-
- }
- }
-
- else if (event->what == mouseDown) /* mouse was clicked */
- {
- eventPoint = event->where; /* get the location of click*/
- GlobalToLocal(&eventPoint); /* got to make it local */
-
- /* see if the click is inside the scrolling text rectangle */
- if (PtInRect( eventPoint, &(**theText).viewRect ))
- {
- TEActivate(theText);
-
- DestTop = (*theText)->destRect.top;
-
- lineHit = (eventPoint.v - DestTop) / height; /* what line is hit ? */
-
- if(lineHit < 0)
- lineHit = 0;
- if(lineHit > (NUMSTRS -1))
- lineHit = (NUMSTRS -1);
-
-
-
- /* now we need to invert the selection that was clicked on*/
- /* get the starting and ending point of the string */
- startSel = (*theText)->lineStarts[lineHit];
- endSel = (*theText)->lineStarts[(lineHit+1)];
-
- TESetSelect(startSel,endSel,theText); /* set and invert selection */
-
- ZeroScrap(); /* clear out scrap area */
- TECopy(theText); /* copy selection to textedit scrap */
- TES = TEScrapHandle(); /* get a handle to text just copied */
- length = TEGetScrapLen(); /* get length of text copied */
-
- /* NOTE: the text that we have a handle to is just text. It is not*/
- /* a pascal string or a C string, just text. Therefore we cannot */
- /* use it as a argument to SetIText() because it expects a pointer*/
- /* to a pascal Str255 type not just a pointer to char. To get around*/
- /* this we will copy this text into our own storage space and then */
- /* add a null marker to the end. Thus making it a C string. Then we*/
- /* call CtoPstr() with the string and then pass it to SetIText. */
-
- HLock(TES);
-
- strcpy(choosenText,*TES); /* copy text into out storage */
-
- *(choosenText + length) = '\0'; /* add a null to mark end of string*/
-
- CtoPstr(choosenText); /* make it a pascal string */
-
- GetDItem(dp,7,&itype,&ihandle,&irect); /* get the handel to item 7*/
-
- /* set item 7 to the text that was selected */
- SetIText(ihandle,choosenText);
- PtoCstr(choosenText); /* change string back to C format */
- HUnlock(TES);
- result = TRUE;
-
- } /* end if ptinrect */
- else /* see where mouse click was */
- {
-
- partcode = FindControl(eventPoint,dp,&whichControl);
-
- if(partcode == inThumb)
- {
- startValue = GetCtlValue(whichControl);
- bogus = TrackControl(whichControl,eventPoint,0);
- endValue = GetCtlValue(whichControl);
- ScrollText(whichControl);
- result = TRUE;
- }
-
- /* only watch events in the scroll bar */
- else if(partcode >= inUpButton)
- {
- bogus = TrackControl(whichControl,eventPoint,&scrollAction);
- result = TRUE;
- }
-
- }
-
-
- } /* end else if (event->what == mouseDown) */
-
- return(result);
- }
-
-
-
-
- /*=============================================================================
- * ProcedureDoDialog1()
- * this is where all the dialog routines are set up.
- * For this Dialog I will use two user items. One for the bold outline on
- * the default button and the other for the scrolling text and its rect.
- * I will also be using a filter proc to handle the modal dialog events the
- * way I want them.
- *===========================================================================*/
- DoDialog1()
- {
- short itemHit,itype,x;
- GrafPtr savePort;
- Rect irect;
- Handle ihandle;
- char flag;
-
- GetPort(&savePort); /* save the current port*/
- myWindow = GetNewDialog(500,0,-1);
-
- /* set up the 2 user items for the dialog */
- SetDItem(myWindow,5,userItem,&DrawScrollText,&irect);
- SetDItem(myWindow,6,userItem,&Dobold,&irect);
-
- SetPort(myWindow); /* dialog is current port*/
- ShowWindow(myWindow);
-
- flag = TRUE;
- while(flag)
- {
- ModalDialog(&scrollFilter,&itemHit); /* use a filter routine*/
- switch(itemHit)
- {
- case 1: /* OK*/
- /* insert ok procedures here */
- flag = FALSE; /* Done with dialog*/
- break;
- case 2: /* CANCEL*/
- /* insert cancel procedures here */
- flag = FALSE;
- break;
-
- } /* END itemHit switch*/
- } /* END while TRUE*/
-
-
- TEDispose(theText); /* get rid of text edit */
- DisposDialog(myWindow); /* get rid of Dialog */
- SetPort(savePort); /* restore old port*/
-
- } /* END */
-
-
- /*=========================================================================*/
-
- UpdateWind(wp)
-
- WindowPtr wp;
- {
-
- BeginUpdate(wp);
-
- SetPort(wp);
-
- EndUpdate(wp);
- }
- /*=========================================================================*/
-
-
- /*=========================================================================*/
-
- checkClick()
- {
-
- SysBeep(1);
-
- } /* end of checkClick */
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-